/*
 * HWaccess.cpp
 *
 *  Created on: 11.04.2011
 *      Author: Jasper
 */

#include "HWaccess.h"

pthread_mutex_t HWaccess::writeLock;
int HWaccess::portAVal;
int HWaccess::portCVal;

HWaccess::HWaccess()
{
}

HWaccess::~HWaccess()
{
}

int HWaccess::init()
{
    portAVal = 0;
    portCVal = 0;

    if(pthread_mutex_init(&writeLock, 0) != 0)
        return -1;

    if (-1 == ThreadCtl(_NTO_TCTL_IO, 0))
        return -1;

    out8(DIO_BASEADDR + DIO_CONTROL_OFFSET, 0x82);

    return 0;
}

int HWaccess::set(const int port, const int val)
{
    int _port = (port >> 8) & 0xFF;
    int _bit = port & 0xFF;

    if((_port != DIO_PORTA_OFFSET && _port != DIO_PORTC_OFFSET)
            || (_port == DIO_PORTC_OFFSET && (_bit&0xF) == 0))
        return -1;

    if(pthread_mutex_lock(&writeLock) != 0)
        return -1;

    if(_port == DIO_PORTA_OFFSET)
    {
        if(val)
            portAVal |= _bit;
        else
            portAVal &= ~_bit;

        out8(DIO_BASEADDR + DIO_PORTA_OFFSET, portAVal);
    }
    else
    {
        if(val)
            portCVal |= _bit;
        else
            portCVal &= ~_bit;

        out8(DIO_BASEADDR + DIO_PORTC_OFFSET, portCVal);
    }

    if (pthread_mutex_unlock(&writeLock) != 0)
        return -1;

    return 0;
}

int HWaccess::setV(const int* portV, const int* valV, const int size)
{
    if(size <= 0)
        return 0;

    int _maskA = 0;
    int _maskC = 0;
    int _bitA = 0;
    int _bitC = 0;

    for(int i = 0; i < size; i++)
    {
        int _port = (portV[i] & 0xFF00) >> 8;
        int _bit = portV[i] & 0xFF;
        if((_port != DIO_PORTA_OFFSET && _port != DIO_PORTC_OFFSET)
                || (_port == DIO_PORTC_OFFSET && (_bit&0xF) == 0))
            return -1;

        if(_port == DIO_PORTA_OFFSET)
        {
            _maskA |= _bit;
            _bitA |= valV[i]==0?0:_bit;
        }
        else
        {
            _maskC |= _bit;
            _bitC |= valV[i]==0?0:_bit;
        }
    }

    if(pthread_mutex_lock(&writeLock) != 0)
        return -1;

    if(_maskA != 0)
    {
        portAVal &= ~_maskA;
        portAVal |= _bitA;

        out8(DIO_BASEADDR + DIO_PORTA_OFFSET, portAVal);
    }

    if(_maskC != 0)
    {
        portCVal &= ~_maskC;
        portCVal |= _bitC;

        out8(DIO_BASEADDR + DIO_PORTC_OFFSET, portCVal);
    }

    if (pthread_mutex_unlock(&writeLock) != 0)
        return -1;

    return 0;
}

int HWaccess::get(const int port, int* resu)
{
    int _port = (port >> 8) & 0xFF;
    int _bit = port & 0xFF;
    if((_port != DIO_PORTB_OFFSET && _port != DIO_PORTC_OFFSET)
            || !(_port == DIO_PORTC_OFFSET && (_bit&0xF0) == 0))
        return -1;

    if(_port == DIO_PORTB_OFFSET)
        *resu = (in8(DIO_BASEADDR + DIO_PORTB_OFFSET) & _bit)==0?0:1;
    else
        *resu = (in8(DIO_BASEADDR + DIO_PORTC_OFFSET) & _bit)==0?0:1;

    return 0;
}

int HWaccess::getV(const int* portV, int* resuV, const int size)
{
    if(size <= 0)
        return 0;

    int _valB = in8(DIO_BASEADDR + DIO_PORTB_OFFSET);
    int _valC = in8(DIO_BASEADDR + DIO_PORTC_OFFSET);

    for(int i = 0; i < size; i++)
    {
        int _port = (portV[i] & 0xFF00) >> 8;
        int _bit = portV[i] & 0xFF;
        if((_port != DIO_PORTB_OFFSET && _port != DIO_PORTC_OFFSET)
                || (_port == DIO_PORTC_OFFSET && (_bit&0xF0) == 0))
            return -1;

        if(_port == DIO_PORTB_OFFSET)
        {
            resuV[i] = (_valB&_bit)==0?0:1;
        }
        else
        {
            resuV[i] = (_valC&_bit)==0?0:1;
        }
    }
    return 0;
}

